package com.wthink.newMain.main.viewmodel

import android.text.TextUtils
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wthink.hzgj.data.BusRepository
import com.wthink.hzgj.data.Result
import com.wthink.hzgj.data.domain.BusDispatch
import com.wthink.hzgj.data.domain.BusStateA
import com.wthink.hzgj.data.domain.Location
import com.wthink.hzgj.data.repository.DefaultBusRepository
import com.wthink.hzgj.home.data.Line
import com.wthink.hzgj.service.DevService
import com.wthink.hzgj.station.data.DefaultStationRepository
import com.wthink.hzgj.station.data.Station
import com.wthink.hzgj.util.Page
import com.wthink.hzgj.util.PreferencesUtils
import com.wthink.hzgj.util.`interface`.SchedleRefuseCallBack
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.collect
import java.math.BigDecimal
import java.text.SimpleDateFormat

class NewHomemodel : ViewModel() {

    var speedLimit  =MutableLiveData("")

    var mix = 0L
    val now = MutableLiveData("")
    val devStatus = MutableLiveData("")
    val gpsState = MutableLiveData(Location(0.0, 0.0, 0))
    val line = MutableLiveData(Line("", ""))
    val cardId = MutableLiveData("")

    private val repository = DefaultStationRepository()

    val stationList = MutableLiveData(emptyList<Station>())
    val upDir = MutableLiveData(true)
    val startStation = MutableLiveData("")
    val station1 = MutableLiveData("")
    val station2 = MutableLiveData("")
    val station3 = MutableLiveData("")
    val station4 = MutableLiveData("")
    val station5 = MutableLiveData("")
    val endStation = MutableLiveData("")

    val currentStation = MutableLiveData("")
    val isUir = MutableLiveData(false)

    val isReal = MutableLiveData(true)

    private val busRepository: BusRepository = DefaultBusRepository()

    val lineList = MutableLiveData(
        Page(
            emptyList<Line>(), 0, 1
        )
    )

    fun start() {
        getCurrentTime()
        viewModelScope.launch(Dispatchers.IO) {
            val sdf = SimpleDateFormat("HH:mm:ss")
            while (isActive) {
                val nowTime: BigDecimal =
                    BigDecimal(mix).add(BigDecimal(System.currentTimeMillis()))
                now.postValue(sdf.format(nowTime))
                delay(200)
            }
        }

        queryGps()
        waitGps()

        waitSchedleRefuseState()
        waitBusState()

        waitSpeedLimit()

        viewModelScope.launch(Dispatchers.IO) {
            if (lineList.value!!.list.isEmpty()) {
                lineList.postValue(
                    busRepository.getLinePage(lineList.value!!.page, true)
                )
/*
                if (lineList.value!!.list.isNotEmpty()) {
                    line.postValue(lineList.value!!.list[0])
                }
*/
            }

            busRepository.refresh()?.let {
                it.join()
                lineList.postValue(
                    busRepository.getLinePage(lineList.value!!.page, true).apply {
                        val selectId = getSelectLine()?.id
                        if (selectId != null) {
                            list.find { it.id.equals(selectId) }?.select = true
                        }
                    }
                )

/*
                if (lineList.value!!.list.isNotEmpty()) {
                    val lineId = PreferencesUtils.getStringObject("lineId")
                    if (!TextUtils.isEmpty(lineId) && lineId != "0") {
                        val findLine = repository.busRepository.findLineById(lineId)
                        line.postValue(Line(findLine?.line!!, findLine?.name))
                        loadStationList(lineId, findLine.line, true)
                    } else {
                        line.postValue(lineList.value!!.list[0])
                        loadStationList(line.value!!.id, line.value!!.name, true)
                    }
                    Log.d("etttetee","lineIdisNotEmpty" + line.value!!.name)

                }
*/
            }
        }
        queryBusStateUntilSuccess()
        getDevStatus()
    }

    private fun selectLine(id: String) {
        val newLineList = lineList.value!!.list.map {
            Line(it.id, it.name, it.id == id)
        }
        lineList.postValue(Page(newLineList, lineList.value!!.page, lineList.value!!.pageTotal))
    }

    private fun getSelectLine(): Line? {
        return lineList.value!!.list.find { it.select }
    }

    private fun waitSpeedLimit(){
        viewModelScope.launch(Dispatchers.IO) {
            DevService.listenSpeedLimit().collect {
                speedLimit.postValue(it)
            }
        }
    }

    private fun waitBusState() {
        viewModelScope.launch(Dispatchers.IO) {
            DevService.listenBusState().collect {
                val value = stationList.value
                if (value != null && value.isNotEmpty()) {
                    val get = value?.get(value.size - 1)
                    Log.d(
                        "newHomeModel",
                        "waitBusState" + it.stationName + "..." + get!!.name + "..." + it.arriveOrLeaving
                    )
                    if (get.name == it.stationName && it.arriveOrLeaving == "2") {
                        return@collect
                    }
                }
                selectLine(it.lineId)
                updateStation(it, it.upDir)
                currentStation.postValue(it.stationName)
                line.postValue(Line(it.lineId, it.lineName))
                if (it.arriveOrLeaving == "1") {
                    isUir.postValue(true)
                } else if (it.arriveOrLeaving == "2") {
                    isUir.postValue(false)
                }
            }
        }
    }

    fun queryGps() {
        viewModelScope.launch(Dispatchers.IO) {
            while (isActive) {
                val ret = DevService.queryGps()
                if (ret is Result.Success) {
                    gpsState.postValue(ret.data)
                    if (ret.data.speed > 60) {
                    }
                }
                delay(1000)
            }
        }
    }

    private fun getCurrentTime(delay: Long = 1000 * 10) {
        viewModelScope.launch(Dispatchers.IO) {
            while (isActive) {
                val ret = DevService.getTime()
                if (ret is Result.Success) {
                    val data = ret.data * 1000
                    mix = data - System.currentTimeMillis() + 1000 * 60 * 60 * 8
                    PreferencesUtils.saveValue("mix", mix)
                }
                delay(delay)
            }
        }
    }

    fun waitGps() {
        viewModelScope.launch(Dispatchers.IO) {
            DevService.listenGps().collect {
                gpsState.postValue(it)

            }
        }
    }

    lateinit var schedleRefuseCallBack: SchedleRefuseCallBack

    fun setRefuseCallBack(callBack: SchedleRefuseCallBack) {
        schedleRefuseCallBack = callBack
    }

    fun waitSchedleRefuseState() {
        viewModelScope.launch(Dispatchers.IO) {
            DevService.listenSchedleRefuse().collect {
                val isRefuse = it
                Log.d("isRefuse", isRefuse)
                schedleRefuseCallBack.callBack(isRefuse)
            }
        }
    }

    private fun setLine(lineId: String, lineName: String, updir: Boolean) {
        Log.d("etttetee", "setLine" + lineName)
        //PreferencesUtils.saveValue("lineId", lineId)
        stationList.postValue(emptyList())
        Log.d("etttetee", "setLine" + line.value!!.name + "生效")
        loadUpdir(lineId, updir)
    }

    fun loadStationList(lineId: String, lineName: String, updir: Boolean) {
        Log.d("etttetee", "loadStationList")
        setLine(lineId, lineName, updir)
        //waitBusState()
    }

    fun queryBusStateUntilSuccess(delay: Long = 30000) {
        viewModelScope.launch(Dispatchers.IO) {
            val ret = DevService.queryBusState()
            if (ret is Result.Success) {
                //updateStation(busState)
                val it = ret.data
                if (it.arriveOrLeaving != "0") {
                    currentStation.postValue(it.stationName)
                    if (it.arriveOrLeaving == "1") {
                        isUir.postValue(true)
                    } else if (it.arriveOrLeaving == "2") {
                        isUir.postValue(false)
                    }
                }

                Log.d("etttetee", it.lineName + "-->" + it.stationName)
                if (it.lineId != "0") {
                    //PreferencesUtils.saveValue("lineId", it.lineId)
                    selectLine(it.lineId)
                    updateStation(it, it.upDir)
                    upDir.postValue(it.upDir)
                    line.postValue(Line(it.lineId, it.lineName))
                } else {
                    loadMorenLine()
                }
            } else {
                loadMorenLine()
            }
        }
    }

    fun loadMorenLine(){
        val lineId = PreferencesUtils.getStringObject("lineId")
        //val lineId = PreferencesUtils.getStringObject("lineId")
        if (!TextUtils.isEmpty(lineId) && lineId != "0") {
            viewModelScope.launch (Dispatchers.IO){
                val findLine = repository.busRepository.findLineById(lineId)
                line.postValue(Line(findLine?.line!!, findLine?.name))
                loadStationList(lineId, findLine.line, true )
            }
        } else {
            line.postValue(lineList.value!!.list[0])
            loadStationList(line.value!!.id, line.value!!.name, true)
        }
    }

    fun getDevStatus() {
        viewModelScope.launch(Dispatchers.IO) {
            val ret = DevService.getDevStatus()
            if (ret is Result.Success) {
                val data = ret.data
                if (data) {
                    devStatus.postValue("营运")
                } else {
                    devStatus.postValue("非营运")
                }
            }
        }
    }

    fun leftBus() {
        if (!currentStation.value.isNullOrEmpty()) {
            if (currentStation.value == startStation.value) {
                if (isUir.value == true) {
                    //当前和首站一致
                } else {
                    isUir.postValue(true)
                    //回到首站
                }
            } else {
                var index = -1;
                val value = stationList.value
                value?.forEachIndexed { inde, station ->
                    if (station.name == currentStation.value) {
                        index = inde
                    }
                }
                if (isUir.value == true) {
                    updateLeftRight(index - 1, false)
                } else {
                    updateLeftRight(index, true)
                }
            }
        }
    }

    fun rightBus() {
        if (!currentStation.value.isNullOrEmpty()) {
            if (currentStation.value == endStation.value) {
                if (isUir.value == true) {
                    //当前和终点站一致
                } else {
                    isUir.postValue(true)
                    //回到首站
                }
            } else {
                var index = -1;
                val value = stationList.value
                value?.forEachIndexed { inde, station ->
                    if (station.name == currentStation.value) {
                        index = inde
                    }
                }
                if (index == value!!.size - 1)
                    return
                if (isUir.value == true) {
                    updateLeftRight(index, false)
                } else {
                    updateLeftRight(index + 1, true)
                }
            }
        } else {
            currentStation.value = startStation.value
            if (isUir.value == true) {
                //当前和终点站一致
            } else {
                isUir.postValue(true)
                //回到首站
            }
        }
    }

    fun updateLine(busDispatch: BusDispatch?) {
        loadStationList(busDispatch!!.line, busDispatch.ccbh, busDispatch.ywlx == 1)
    }

    fun playStation() {
        if (currentStation.value!!.isNotEmpty()) {
            viewModelScope.launch(Dispatchers.IO) {
                val value = stationList.value
                value!!.forEach {
                    if (currentStation.value == it.name) {
                        DevService.stationVoice(line.value!!.id, it.id, isUir.value!!)
                        return@forEach
                    }
                }
            }
        }
    }

    fun loadUpdir(lineId: String, updir: Boolean = true) {
        upDir.postValue(updir)
        viewModelScope.launch(Dispatchers.IO) {
            //  stationList.postValue(repository.getStationList(line.value!!.id, updir))
            //  val stationlist = repository.getStationList(line.value!!.id, updir)
            val findLineById = repository.busRepository.findLineById(lineId)
            line.postValue(Line(findLineById!!.line,findLineById.name))
            stationList.postValue(repository.getStationList(lineId, updir))
            val stationlist = repository.getStationList(lineId, updir)
            Log.d("etttetee", "loadUpdir" + stationlist.size)
            Log.d("etttetee", "loadUpdir" + line.value!!.name)
            if (stationlist.isEmpty()) {
                return@launch
            }
            startStation.postValue(stationlist[0].name)
            when {
                stationlist.size >= 7 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[4].name)
                    station5.postValue(stationlist[5].name)
                    endStation.postValue(stationlist[stationlist.size - 1].name)
                }
                stationlist.size == 2 -> {
                    station1.postValue(stationlist[1].name)
                    station1.postValue("")
                    station2.postValue("")
                    station3.postValue("")
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 3 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue("")
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 4 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[stationlist.size - 1].name)
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 5 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[stationlist.size - 1].name)
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 6 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[4].name)
                    station5.postValue(stationlist[stationlist.size - 1].name)
                    endStation.postValue("")
                }
            }
        }
    }

    private fun updateLeftRight(index: Int, isuir: Boolean) {
        viewModelScope.launch(Dispatchers.IO) {
            stationList.postValue(repository.getStationList(line.value!!.id, upDir.value!!))
            val stationlist = repository.getStationList(line.value!!.id, upDir.value!!)
            startStation.postValue(stationlist[0].name)
            if (index <= stationlist.size - 1) {
                currentStation.postValue(stationlist[index].name)
                isUir.postValue(isuir)
            }
            when {
                stationlist.size >= 7 -> {
                    when (index) {
                        0, 1, 2, 3 -> {
                            station1.postValue(stationlist[1].name)
                            station2.postValue(stationlist[2].name)
                            station3.postValue(stationlist[3].name)
                            station4.postValue(stationlist[4].name)
                            station5.postValue(stationlist[5].name)
                            endStation.postValue(stationlist[stationlist.size - 1].name)
                            isReal.postValue(true)
                        }

                        in 4..stationlist.size - 4 -> {
                            station1.postValue(stationlist[index - 2].name)
                            station2.postValue(stationlist[index - 1].name)
                            station3.postValue(stationlist[index].name)
                            station4.postValue(stationlist[index + 1].name)
                            station5.postValue(stationlist[index + 2].name)
                            endStation.postValue(stationlist[stationlist.size - 1].name)
                        }

                        stationlist.size - 3, stationlist.size - 2, stationlist.size - 1 -> {
                            station1.postValue(stationlist[stationlist.size - 6].name)
                            station2.postValue(stationlist[stationlist.size - 5].name)
                            station3.postValue(stationlist[stationlist.size - 4].name)
                            station4.postValue(stationlist[stationlist.size - 3].name)
                            station5.postValue(stationlist[stationlist.size - 2].name)
                            endStation.postValue(stationlist[stationlist.size - 1].name)
                            isReal.postValue(true)

                        }
                    }
                }
                stationlist.size == 2 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue("")
                    station3.postValue("")
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 3 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue("")
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 4 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[stationlist.size - 1].name)
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 5 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[stationlist.size - 1].name)
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 6 -> {
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[4].name)
                    station5.postValue(stationlist[stationlist.size - 1].name)
                    endStation.postValue("")
                }
            }
        }
    }

    private fun updateStation(busState: BusStateA, updir: Boolean = true) {
        Log.d("newHomeModel", "updateStation")
        upDir.postValue(updir)
        viewModelScope.launch(Dispatchers.IO) {
            stationList.postValue(repository.getStationList(busState.lineId, updir))
            val stationlist = repository.getStationList(busState.lineId, updir)
            if (stationlist.isEmpty()) {
                return@launch
            }
            var index = -1
            stationlist.forEachIndexed { dex, station ->
                if (station.name == busState.stationName) {
                    index = dex
                }
            }
            Log.d("indexxx", "$index")
            when {
                stationlist.size >= 7 -> {
                    when (index) {
                        -1, 0, 1, 2, 3 -> {
                            startStation.postValue(stationlist[0].name)
                            station1.postValue(stationlist[1].name)
                            station2.postValue(stationlist[2].name)
                            station3.postValue(stationlist[3].name)
                            station4.postValue(stationlist[4].name)
                            station5.postValue(stationlist[5].name)
                            endStation.postValue(stationlist[stationlist.size - 1].name)
                            isReal.postValue(true)
                        }

                        in 4..stationlist.size - 4 -> {
                            startStation.postValue(stationlist[0].name)
                            station1.postValue(stationlist[index - 2].name)
                            station2.postValue(stationlist[index - 1].name)
                            station3.postValue(stationlist[index].name)
                            station4.postValue(stationlist[index + 1].name)
                            station5.postValue(stationlist[index + 2].name)
                            endStation.postValue(stationlist[stationlist.size - 1].name)
                            isReal.postValue(true)
                        }

                        stationlist.size - 3, stationlist.size - 2, stationlist.size - 1 -> {
                            startStation.postValue(stationlist[0].name)
                            station1.postValue(stationlist[stationlist.size - 6].name)
                            station2.postValue(stationlist[stationlist.size - 5].name)
                            station3.postValue(stationlist[stationlist.size - 4].name)
                            station4.postValue(stationlist[stationlist.size - 3].name)
                            station5.postValue(stationlist[stationlist.size - 2].name)
                            endStation.postValue(stationlist[stationlist.size - 1].name)
                            isReal.postValue(false)
                        }
                    }
                }
                stationlist.size == 2 -> {
                    startStation.postValue(stationlist[0].name)
                    station1.postValue(stationlist[1].name)
                    station2.postValue("")
                    station3.postValue("")
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 3 -> {
                    startStation.postValue(stationlist[0].name)
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue("")
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 4 -> {
                    startStation.postValue(stationlist[0].name)
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[stationlist.size - 1].name)
                    station4.postValue("")
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 5 -> {
                    startStation.postValue(stationlist[0].name)
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[stationlist.size - 1].name)
                    station5.postValue("")
                    endStation.postValue("")
                }
                stationlist.size == 6 -> {
                    startStation.postValue(stationlist[0].name)
                    station1.postValue(stationlist[1].name)
                    station2.postValue(stationlist[2].name)
                    station3.postValue(stationlist[3].name)
                    station4.postValue(stationlist[4].name)
                    station5.postValue(stationlist[stationlist.size - 1].name)
                    endStation.postValue("")
                }
            }
        }
    }

}